// Ninf-G-XX, ver. 0.1
// Copyright 2011 National Institute of Advanced Industrial Science and Technology
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "grpc.h"
#include "grpc_data.h"

/**
 * just to test
 *
 */
#include "FpOutputStream.hpp"
#include "FpInputStream.hpp"
#include "DataOutputStream.hpp"
#include "DataInputStream.hpp"
#include "GrpcData.hpp"
#include "ByteArrayOutputStream.hpp"

#include "ByteArrayInputStream.hpp"


int test2(){
  ByteArrayOutputStream bo(2,2);
  char a [] = {0x00, 0xaa, 0xab};
  bo.write(0xbb);
  bo.write(0x00);
  bo.write(0x12);
  bo.write(a, 0, 3);
  bo.dump();

  ByteArrayInputStream bi(bo.getBytes(), bo.length());
  int c;
  while ((c = bi.read()) >= 0)
    printf("%02x ", 0xff & c);
  printf("\n");

  ByteArrayInputStream bi2(bo.getBytes(), bo.length());
  char buf[20];
  printf("read %d\n", bi2.read(buf, 0, 2));
  printf("read %d\n", bi2.readFully(buf, 2, 10));
  for (int i = 0; i < 10; i++)
    printf("%02x ", 0xff & buf[i]);
  printf("\n");
}



#define N 3
double A [N * N]  = {0, 1, 2, 3, 4, 5, 6, 7, 8};
double B [N * N]  = {0, 0, 0, 0, 0, 0, 0, 0, 0};
double C [N * N]  = {0, 0, 0, 0, 0, 0, 0, 0, 0};

int test(){


  grpc_data_t dA;

  grpc_data_memory_mapping_set("A", A);
  grpc_data_init(&dA,
        (const char * []){"memory://localhost/A", NULL},
        NULL,
        GRPC_MATRIX_OF_DOUBLE,
        (size_t []){3, 3, 0},
        (grpc_data_mode_t*)(GRPC_VOLATILE, GRPC_END_LIST)
    );

  /** save test
   * this should create a file at current dir and
   * put the data in it.
   * */
  //grpc_data_save(&dA, "file:///tmp.A.data");


  std::cout << *((ninf::data::GrpcData *)(dA.realhandle));
  {
    FpOutputStream fo("/tmp/dataA");
    DataOutputStream dos(&fo);
    ((ninf::data::GrpcData *)(dA.realhandle))->writeTo(dos);
    fo.close();
  }
  {
    ByteArrayOutputStream bo;
    DataOutputStream dos(&bo);
    ((ninf::data::GrpcData *)(dA.realhandle))->writeTo(dos);
    bo.close();
    bo.dump();

  }
  ninf::data::GrpcData data;
  {
    FpInputStream fi("/tmp/dataA");
    DataInputStream dis(&fi);
    data.readFrom(dis);
  }
  std::cout << "-------------";
  std::cout << data;

}

int test3(){


  grpc_data_t dA;

  grpc_data_memory_mapping_set("A", A);
  grpc_data_init(&dA,
        (const char * []){"memory://localhost/A", NULL},
        NULL,
        GRPC_MATRIX_OF_DOUBLE,
        (size_t []){3, 3, 0},
        (grpc_data_mode_t*)(GRPC_VOLATILE, GRPC_END_LIST)
    );

//    std::cout << grpc_data_save(&dA, "file:///tmp/tmp.A.data");
  std::cout << grpc_data_save(&dA, "rfile:///rel.A.data");

    //grpc_data_save(&dA, "tmp.A.data");
}

int test4(){


  grpc_data_t dA;

  grpc_data_memory_mapping_set("A", B);
  grpc_data_init(&dA,
        NULL,
        (const char * []){"memory://localhost/A", NULL},
        GRPC_MATRIX_OF_DOUBLE,
        (size_t []){3, 3, 0},
        (grpc_data_mode_t []){GRPC_VOLATILE, GRPC_END_LIST}
        );


  for (int i = 0; i < N * N; i++)
    std::cout << B[i] << " ";
  std::cout << std::endl;


//  std::cout << grpc_data_load(&dA, "file:///tmp/tmp.A.data");
   //grpc_data_save(&dA, "tmp.A.data");
  std::cout << grpc_data_load(&dA, "rfile:///rel.A.data");

  for (int i = 0; i < N * N; i++)
    std::cout << B[i] << " ";
  std::cout << std::endl;

}


int writeDataHandle(){
  grpc_data_t dA;

  grpc_data_memory_mapping_set("A", B);
  grpc_data_init(&dA,
        NULL,
        (const char * []){"memory://localhost/A", NULL},
        GRPC_MATRIX_OF_DOUBLE,
        (size_t []){3, 3, 0},
        (grpc_data_mode_t []){GRPC_VOLATILE, GRPC_END_LIST}
        );

  std::cout << grpc_data_save(&dA, "file:///tmp/handleSave") << std::endl;
}

int readDataHandle(){
  grpc_data_t dA;

  std::cout << grpc_data_load(&dA, "file:///tmp/handleSave") << std::endl;
  std::cout << grpc_data_save(&dA, "file:///tmp/handleSaveCopy") << std::endl;
}

int transfer(){
  grpc_data_t dA;

  grpc_data_memory_mapping_set("A", A);
  grpc_data_memory_mapping_set("B", B);
  grpc_data_init(&dA,
        (const char * []){"memory://localhost/A", NULL},
        (const char * []){"file:///tmp/content0", "file:///tmp/content1", NULL},
        GRPC_MATRIX_OF_DOUBLE,
        (size_t []){3, 3, 0},
        (grpc_data_mode_t []){GRPC_VOLATILE, GRPC_END_LIST}
        );

  std::cout << grpc_data_transfer(&dA, NULL,
      (const char * []){"file:///tmp/content2", "memory://localhost/B", NULL},
        NULL, NULL) << std::endl;
}


int main(){
//  writeDataHandle();
//  readDataHandle();
  transfer();
}
